package com.kelp.codetoolkit.ui.form

import com.intellij.database.util.common.isNotNullOrEmpty
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.ComboBox
import com.intellij.openapi.ui.popup.JBPopup
import com.intellij.openapi.ui.popup.JBPopupFactory
import com.intellij.psi.PsiClass
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiMethod
import com.intellij.ui.JBColor
import com.intellij.ui.components.JBList
import com.intellij.ui.components.JBScrollPane
import com.intellij.ui.util.preferredWidth
import com.kelp.codetoolkit.cache.CollectionPsiClassCache
import com.kelp.codetoolkit.constant.MethodConstant
import com.kelp.codetoolkit.data.ListCellData
import com.kelp.codetoolkit.data.ResponseParamDetailData
import com.kelp.codetoolkit.enums.JavaCollectionEnum
import com.kelp.codetoolkit.renderer.ParamClassListCellRenderer
import com.kelp.codetoolkit.respository.CodeToolkitGlobalSettingRepository
import com.kelp.codetoolkit.service.MethodDialogHandleService
import java.awt.Dimension
import java.awt.FlowLayout
import java.awt.event.KeyAdapter
import java.awt.event.KeyEvent
import javax.swing.*
import javax.swing.border.LineBorder
import javax.swing.event.DocumentEvent
import javax.swing.event.DocumentListener

/**
 * @author: liuyuebai
 * @date: 2025/1/24 11:03
 * @description:
 */
class MethodResponsePanel(project: Project):JPanel() {

    // 创建ComboBoxModel并设置数据
    private val responseParamBoxModel: DefaultComboBoxModel<String> = DefaultComboBoxModel()
    private val responseBoxKeyModel: DefaultComboBoxModel<String> = DefaultComboBoxModel(MethodConstant.getMapWrapperKey())
    private val responseParamPanel = JPanel(FlowLayout(FlowLayout.LEFT))
    private val responseParamLabel: JLabel = JLabel("Controller View Response Param：")
    private val responseParam: JTextField = JTextField(15)
    private val businessLogicReturnParamLabel: JLabel = JLabel("Business Login Return Param：")
    private val businessLogicReturnParam: JTextField = JTextField(15)
    private val responseBoxLabel: JLabel = JLabel(" Response  Collection  Wrapper：")
    private val responseBox: ComboBox<String> = ComboBox(responseParamBoxModel)
    private val responseBoxKeyLabel: JLabel = JLabel("Response Map Wrapper Key：")
    private val responseBoxKey: ComboBox<String> = ComboBox(responseBoxKeyModel)

    //响应参数处理
    private var responseParamData: ResponseParamDetailData = ResponseParamDetailData()

    private var currentPopup: JBPopup? = null

    //筛选返回响应参数
    private val viewResponseListModel: DefaultListModel<ListCellData> = DefaultListModel()
    private val viewResponseList: JList<ListCellData> = JBList(viewResponseListModel)
    private val viewResponseScrollPane: JScrollPane = JBScrollPane(viewResponseList)

    // 当前页码，初始化为0
    private var viewResponseCurrentPage = 0
    // 总页数，初始设为0，后续根据数据总量动态更新
    private var viewResponseTotalPages = 0
    // 用于标记是否监听文档变化，初始化为true表示默认监听
    private var viewResponseListenerEnabled = true

    //筛选返回响应参数
    private val businessLogicReturnParamListModel: DefaultListModel<ListCellData> = DefaultListModel()
    private val businessLogicReturnParamList: JList<ListCellData> = JBList(businessLogicReturnParamListModel)
    private val businessLogicReturnParamScrollPane: JScrollPane = JBScrollPane(businessLogicReturnParamList)

    // 当前页码，初始化为0
    private var businessLogicReturnParamCurrentPage = 0
    // 总页数，初始设为0，后续根据数据总量动态更新
    private var businessLogicReturnParamTotalPages = 0
    // 用于标记是否监听文档变化，初始化为true表示默认监听
    private var businessLogicReturnParamListenerEnabled = true



    init {
        //选中
        val selectCollectionWrapper = MethodConstant.getSelectCollectionWrapper()
        val pageSetting = CodeToolkitGlobalSettingRepository.getInstance(project).state.getPageSetting()
        if (pageSetting.isNotNullOrEmpty){
            val pageArr = pageSetting.split(".")
            selectCollectionWrapper.add(pageArr[pageArr.size - 1])
        }
        //map
        selectCollectionWrapper.forEach { collectionWrapper-> responseParamBoxModel.addElement(collectionWrapper) }
        responseBox.isEnabled = false
        responseBoxKey.isEnabled = false
        responseBox.preferredSize = Dimension(170,35)
        responseBoxKey.preferredSize = Dimension(170,35)
        //响应参数处理
        handleViewResponseParam(project)
        //处理返回参数
        handleBusinessLogicReturnParamParam(project)
    }

    fun getResponseParamPanel(): JPanel{
        // 创建一个新面板用于添加responseParam和responseBox到第三行
        responseParamPanel.layout = BoxLayout(responseParamPanel, BoxLayout.Y_AXIS) // 设置mainPanel的布局为垂直排列

        // 使用FlowLayout.LEFT，但需要注意组件的自然宽度可能会影响对齐
        val responseOneLinePanel = JPanel(FlowLayout(FlowLayout.LEFT, 5, 5)) // 增加组件间的水平和垂直间距
        responseOneLinePanel.add(responseParamLabel)
        responseOneLinePanel.add(Box.createHorizontalStrut(2)) // 添加空白间隔以改善对齐
        responseOneLinePanel.add(responseParam)
        responseOneLinePanel.add(Box.createHorizontalStrut(5)) // 添加空白间隔以改善对齐
        responseOneLinePanel.add(businessLogicReturnParamLabel)
        responseOneLinePanel.add(Box.createHorizontalStrut(3)) // 添加空白间隔以改善对齐
        responseOneLinePanel.add(businessLogicReturnParam)

        val responseTwoLinePanel = JPanel(FlowLayout(FlowLayout.LEFT, 5, 5)) // 增加组件间的水平和垂直间距
        responseTwoLinePanel.add(responseBoxLabel)
        responseTwoLinePanel.add(Box.createHorizontalStrut(10)) // 添加空白间隔以改善对齐
        responseTwoLinePanel.add(responseBox)
        responseTwoLinePanel.add(Box.createHorizontalStrut(6)) // 添加空白间隔以改善对齐
        responseTwoLinePanel.add(responseBoxKeyLabel)
        responseTwoLinePanel.add(Box.createHorizontalStrut(10)) // 添加空白间隔以改善对齐
        responseTwoLinePanel.add(responseBoxKey)

        responseParamPanel.add(responseOneLinePanel)
        responseParamPanel.add(responseTwoLinePanel)
        // 定义浅灰色
        val lightGray = JBColor.GRAY
        // 创建宽度为 1 像素、颜色为浅灰色的 LineBorder
        val lineBorder = LineBorder(lightGray, 1)
        // 创建带有标题的边框，使用上面创建的 LineBorder 作为边框
        val titledBorder = BorderFactory.createTitledBorder(lineBorder, "Response Param")
        responseParamPanel.setBorder(titledBorder)
        return responseParamPanel
    }

    fun getResponseParamData(): ResponseParamDetailData {
        return responseParamData
    }

    /**
     * 处理响应
     */
    private fun handleViewResponseParam(project: Project){
        // 为requestPBoxOne添加监听器，根据其值控制requestPBoxKeyOne的显示
        responseBox.addActionListener {
            val selectedItem = responseBox.selectedItem as String
            responseBoxKey.isEnabled = selectedItem  == "Map"
            val collectionEnum = JavaCollectionEnum.getByName(selectedItem)
            responseParamData.collectionName = selectedItem
            if (null != collectionEnum) {
                val psiClass = CollectionPsiClassCache.getCache(project, collectionEnum.qualifiedName)
                responseParamData.collectionParamPsiClass = psiClass
            }
            val pageSetting = CodeToolkitGlobalSettingRepository.getInstance(project).state.getPageSetting()
            if (pageSetting.isNotNullOrEmpty) {

                val pageArr = pageSetting.split(".")
                if (pageArr[pageArr.size - 1] == selectedItem){
                    val psiClass = CollectionPsiClassCache.getCache(project, pageSetting)
                    responseParamData.collectionParamPsiClass = psiClass
                }
            }
        }

        responseBoxKey.addActionListener {
            val selectedItem = responseBoxKey.selectedItem as String
            responseParamData.mapKey = selectedItem
        }
        
        val listener = object : DocumentListener {
            override fun insertUpdate(e: DocumentEvent) {
                println("responseParam insertUpdate isDocumentListenerEnabled:$viewResponseListenerEnabled")
                if (!viewResponseListenerEnabled){
                    return
                }
                commonHandleResponse(project)
            }
            override fun removeUpdate(e: DocumentEvent) {
                println("responseParam removeUpdate isDocumentListenerEnabled:$viewResponseListenerEnabled")
                if (!viewResponseListenerEnabled){
                    return
                }
                commonHandleResponse(project)
            }
            override fun changedUpdate(e: DocumentEvent) {
                println("responseParam changedUpdate isDocumentListenerEnabled:$viewResponseListenerEnabled")
                if (!viewResponseListenerEnabled){
                    return
                }
                commonHandleResponse(project)
            }
        }

        // 重新添加文档监听器，以便再次监听文本框内容变化
        responseParam.document.addDocumentListener(listener)

        //添加键盘按键监听
        responseParam.addKeyListener(object : KeyAdapter() {
            override fun keyTyped(e: KeyEvent) {
                println("responseParam addKeyListener keyTyped: ${e.keyChar}")
                viewResponseListenerEnabled = true
            }

            override fun keyPressed(e: KeyEvent) {
                println("responseParam addKeyListener keyPressed: ${e.keyCode}")
                viewResponseListenerEnabled = true
            }

            override fun keyReleased(e: KeyEvent) {
                println("responseParam addKeyListener keyReleased: ${e.keyCode}")
                viewResponseListenerEnabled = true
            }
        })

        // 添加选择事件监听器
        viewResponseList.addListSelectionListener {
            if (!it.valueIsAdjusting) {
                val selectedIndex = viewResponseList.selectedIndex
                if (selectedIndex!= -1) {
                    println("responseParam addListSelectionListener selectedIndex:$selectedIndex")
                    viewResponseScrollPane.isVisible = false
                    responseBox.isEnabled = true
                    currentPopup?.closeOk(null)
                    // 移除文档监听器
                    viewResponseListenerEnabled = false
                    val selectData = viewResponseListModel.elementAt(selectedIndex)
                    responseParam.text = selectData?.shortClassName
                    responseParamData.shortClassName = selectData?.shortClassName?:""
                    responseParamData.paramClass = selectData?.psiClass
                }
            }
        }
        // 添加滚动监听器到responseScrollPane
        var previousScrollPosition = 0 // 初始化上一次滚动位置
        var previousPage = 0
        // 添加滚动监听器到selectScrollPane
        viewResponseScrollPane.viewport.addChangeListener { e ->
            println("responseScrollPane addChangeListener isDocumentListenerEnabled:$viewResponseListenerEnabled")
            if (!viewResponseListenerEnabled){
                return@addChangeListener
            }
            val viewport = e.source as JViewport
            val viewportHeight = viewport.extentSize.height
            val maxScrollPosition = viewport.viewSize.height - viewportHeight
            val currentScrollPosition = viewport.viewPosition.y
            val thresholdTop = 1 // 距离顶部的阈值，可根据实际情况调整
            val thresholdBottom = 1 // 距离底部的阈值，可根据实际情况调整

            // 检测滚动方向
            if (currentScrollPosition < previousScrollPosition - thresholdTop && viewResponseCurrentPage > 1) {
                // 向上滚动，向上翻页
                viewResponseCurrentPage--
                println("responseScrollPane addChangeListener scrolling up $viewResponseCurrentPage")
            } else if (currentScrollPosition >= maxScrollPosition - thresholdBottom && viewResponseCurrentPage < viewResponseTotalPages) {
                // 向下滚动，向下翻页
                viewResponseCurrentPage++
                if (viewResponseCurrentPage >= viewResponseTotalPages){
                    viewResponseCurrentPage = viewResponseTotalPages
                }
                println("responseScrollPane addChangeListener scrolling down ${viewResponseCurrentPage}")
            }
            // 更新上一次滚动位置
            previousScrollPosition = currentScrollPosition

            // 根据新的页码执行搜索
            if (viewResponseCurrentPage != previousPage) { // 假设previousPage是跟踪上一次页码的变量
                commonResponse(project)
                // 更新previousPage
                previousPage = viewResponseCurrentPage
            }
        }
    }

    private fun commonHandleResponse(project: Project){
        viewResponseCurrentPage = 0
        viewResponseListModel.clear()
        commonResponse(project)
        updateParamOptions(responseParam,viewResponseList, viewResponseScrollPane)
    }

   private fun commonResponse(project:Project){
       val methodDialogHandleService = MethodDialogHandleService.getInstance(project)
       val dataList = methodDialogHandleService.filterSearchByCache(responseParam.text,project)
       viewResponseTotalPages = dataList.size / MethodConstant.getCommonPageSize() + 1
       val searchPageData = methodDialogHandleService.assembleCellData(dataList,viewResponseCurrentPage, project)
       viewResponseListModel.addAll(searchPageData)
   }

    /**
     * 处理响应
     */
    private fun handleBusinessLogicReturnParamParam(project: Project){
        val listener = object : DocumentListener {
            override fun insertUpdate(e: DocumentEvent) {
                if (!businessLogicReturnParamListenerEnabled){
                    return
                }
                commonHandleReturnParam(project)
            }
            override fun removeUpdate(e: DocumentEvent) {
                if (!businessLogicReturnParamListenerEnabled){
                    return
                }
                commonHandleReturnParam(project)
            }
            override fun changedUpdate(e: DocumentEvent) {
                if (!businessLogicReturnParamListenerEnabled){
                    return
                }
                commonHandleReturnParam(project)
            }
        }

        // 重新添加文档监听器，以便再次监听文本框内容变化
        businessLogicReturnParam.document.addDocumentListener(listener)

        //添加键盘按键监听
        businessLogicReturnParam.addKeyListener(object : KeyAdapter() {
            override fun keyTyped(e: KeyEvent) {
                businessLogicReturnParamListenerEnabled = true
            }

            override fun keyPressed(e: KeyEvent) {
                businessLogicReturnParamListenerEnabled = true
            }
            override fun keyReleased(e: KeyEvent) {
                businessLogicReturnParamListenerEnabled = true
            }
        })

        // 添加选择事件监听器
        businessLogicReturnParamList.addListSelectionListener {
            if (!it.valueIsAdjusting) {
                val selectedIndex = businessLogicReturnParamList.selectedIndex
                if (selectedIndex!= -1) {
                    println("responseParam addListSelectionListener selectedIndex:$selectedIndex")
                    businessLogicReturnParamScrollPane.isVisible = false
                    currentPopup?.closeOk(null)
                    // 移除文档监听器
                    businessLogicReturnParamListenerEnabled = false
                    val selectData = businessLogicReturnParamListModel.elementAt(selectedIndex)
                    businessLogicReturnParam.text = selectData?.shortClassName
                    responseParamData.returnParamShortName = selectData?.shortClassName?:""
                    responseParamData.returnParamClass = selectData?.psiClass
                }
            }
        }
        // 添加滚动监听器到responseScrollPane
        var previousScrollPosition = 0 // 初始化上一次滚动位置
        var previousPage = 0
        // 添加滚动监听器到selectScrollPane
        businessLogicReturnParamScrollPane.viewport.addChangeListener { e ->
            if (!businessLogicReturnParamListenerEnabled){
                return@addChangeListener
            }
            val viewport = e.source as JViewport
            val viewportHeight = viewport.extentSize.height
            val maxScrollPosition = viewport.viewSize.height - viewportHeight
            val currentScrollPosition = viewport.viewPosition.y
            val thresholdTop = 1 // 距离顶部的阈值，可根据实际情况调整
            val thresholdBottom = 1 // 距离底部的阈值，可根据实际情况调整

            // 检测滚动方向
            if (currentScrollPosition < previousScrollPosition - thresholdTop && businessLogicReturnParamCurrentPage > 1) {
                // 向上滚动，向上翻页
                businessLogicReturnParamCurrentPage--
            } else if (currentScrollPosition >= maxScrollPosition - thresholdBottom && businessLogicReturnParamCurrentPage < businessLogicReturnParamTotalPages) {
                // 向下滚动，向下翻页
                businessLogicReturnParamCurrentPage++
                if (businessLogicReturnParamCurrentPage >= businessLogicReturnParamTotalPages){
                    businessLogicReturnParamCurrentPage = businessLogicReturnParamTotalPages
                }
            }
            // 更新上一次滚动位置
            previousScrollPosition = currentScrollPosition

            // 根据新的页码执行搜索
            if (businessLogicReturnParamCurrentPage != previousPage) { // 假设previousPage是跟踪上一次页码的变量
                commonReturnHandle(project)
                // 更新previousPage
                previousPage = businessLogicReturnParamCurrentPage
            }
        }
    }

    private fun commonHandleReturnParam(project: Project){
        businessLogicReturnParamCurrentPage = 0
        businessLogicReturnParamListModel.clear()
        commonReturnHandle(project)
        updateParamOptions(businessLogicReturnParam,businessLogicReturnParamList, businessLogicReturnParamScrollPane)
    }

    private fun commonReturnHandle(project:Project){
        val methodDialogHandleService = MethodDialogHandleService.getInstance(project)
        val dataList = methodDialogHandleService.filterSearchByCache(businessLogicReturnParam.text,project)
        businessLogicReturnParamTotalPages = dataList.size/MethodConstant.getCommonPageSize()+1
        val searchPageData = methodDialogHandleService.assembleCellData(dataList,businessLogicReturnParamCurrentPage, project)
        businessLogicReturnParamListModel.addAll(searchPageData)
    }


    private fun updateParamOptions(paramField: JTextField,selectList: JList<ListCellData>, paramScrollPane: JScrollPane) {
        currentPopup?.closeOk(null)
        // 设置每页展示20条数据
        selectList.setVisibleRowCount(MethodConstant.getCommonPageSize())
        paramScrollPane.preferredSize = Dimension(500, 300)
        paramScrollPane.viewport.view = selectList
        val cellRenderer = ParamClassListCellRenderer()
        cellRenderer.setParamScrollPane(paramScrollPane)
        selectList.cellRenderer = cellRenderer
        paramScrollPane.isVisible = true
        val popupFactory = JBPopupFactory.getInstance()
        currentPopup = popupFactory.createComponentPopupBuilder(paramScrollPane, null)
            .setResizable(true)
            .setMovable(true)
            .createPopup()
        currentPopup?.showUnderneathOf(paramField)
        println("currentPopup:${currentPopup.hashCode()},fieldBoundsY:${paramField.y}")
    }

    fun showResultList(classes: List<PsiClass>, project:Project, invoker: Any) {
        val listModel = DefaultListModel<String>()
        // 每次先显示前 10 条
        classes.take(10).forEach { listModel.addElement(it.qualifiedName ?: "") }
        val list = JBList(listModel)
        val scrollPane = JBScrollPane(list)
        scrollPane.preferredSize = java.awt.Dimension(400, 200) // 设置滚动面板大小，支持滚动查看

        // 监听滚动事件，动态加载更多（如果有剩余数据 ）
        scrollPane.viewport.addChangeListener {
            val viewport = it.source as javax.swing.JViewport
            val extentHeight = viewport.extentSize.height
            val viewHeight = viewport.viewSize.height
            val positionY = viewport.viewPosition.y
            // 滚动到底部附近（距离底部 10 像素内 ）且还有剩余数据
            if (positionY + extentHeight >= viewHeight - 10 && listModel.size < classes.size) {
                val remainingClasses = classes.subList(listModel.size, classes.size)
                remainingClasses.forEach { className ->
                    listModel.addElement(className.qualifiedName ?: "")
                }
            }
        }

        // 创建并显示弹窗（也可替换为其他展示方式，比如嵌入到工具窗口 ）
//        val popup: JBPopup = JBPopupFactory.getInstance()
//            .createComponentPopupBuilder(scrollPane, list)
//            .setTitle("Code Suggestions")
//            .setResizable(true)
//            .setMovable(true)
//            .createPopup()
//        popup.showUnderneathOf(invoker)
    }

}